/**
 * Copyright (c) 2023, iDearHanYu Co., Ltd.
 *
 * SPDX-License-Identifier: 
 *
 * Change Logs:
 * Date           Author       Notes
 * 2024-08-16     chao         first version
 */

#include <lvgl.h>
#include <stdio.h>
#include "virtlcd.h"

typedef struct _pointer {
    uint8_t state;
    uint16_t x;
    uint16_t y;
} pointer_t;

typedef struct _keypad {
    uint8_t state;
    lv_key_t key;
} keypad_t;

typedef struct _encoder {
    uint8_t state;
    int val;
} encoder_t;

typedef struct _button {
    uint8_t state;
    uint32_t btn_id;
} button_t;

/* private variables */
static pointer_t pointer;
static keypad_t keypad;
static encoder_t encoder;
static button_t button;
static lv_indev_t *lv_pointer_device_object;
static lv_indev_t *lv_keypad_device_object;
static lv_indev_t *lv_encoder_device_object;
static lv_indev_t *lv_button_device_object;
static const lv_point_t button_points[LV_USER_BTN_MAX] = {
    {0, 0},
    {0, 1},
    {0, 2},
    {0, 3},
};

static void mouse_callback(int event, int x, int y)
{
//    printf("mouse:%d,%d,%d\n",event,x,y);
    if (event == MOUSE_EVENT_LBDOWN)
    {
        pointer.state = LV_INDEV_STATE_PRESSED;
    }
    else if (event == MOUSE_EVENT_LBUP)
    {
        pointer.state = LV_INDEV_STATE_RELEASED;
    }
    pointer.x = x;
    pointer.y = y;
}

static void keyboard_callback(int event, int key)
{
    printf("keyboard: %d->%s\n", key, event==KEYBD_EVENT_DOWN ? "press" : "release");
    if (event == KEYBD_EVENT_DOWN)
    {
        if (key == 8) //backspace
        {
            keypad.key = LV_KEY_BACKSPACE;
            keypad.state = LV_INDEV_STATE_PRESSED;
        }
        else if (key == 13) //enter
        {
            keypad.key = LV_KEY_ENTER;
            keypad.state = LV_INDEV_STATE_PRESSED;
        }
        else if (key == 27) //esc
        {
            keypad.key = LV_KEY_ESC;
            keypad.state = LV_INDEV_STATE_PRESSED;
        }
        else if (key == 32) //' ' -> play & pause
        {
            button.btn_id = LV_USER_BTN_PLAY_PAUSE;
            button.state = LV_INDEV_STATE_PRESSED;
        }
        else if (key == 33) //page up
        {
            keypad.key = LV_KEY_PREV;
            keypad.state = LV_INDEV_STATE_PRESSED;
        }
        else if (key == 34) //page dwon
        {
            keypad.key = LV_KEY_NEXT;
            keypad.state = LV_INDEV_STATE_PRESSED;
        }
        else if (key == 35) //end
        {
            keypad.key = LV_KEY_END;
            keypad.state = LV_INDEV_STATE_PRESSED;
        }
        else if (key == 36) //home
        {
            keypad.key = LV_KEY_HOME;
            keypad.state = LV_INDEV_STATE_PRESSED;
        }
        else if (key == 37) //left
        {
            keypad.key = LV_KEY_LEFT;
            keypad.state = LV_INDEV_STATE_PRESSED;
        }
        else if (key == 38) //up
        {
            keypad.key = LV_KEY_UP;
            keypad.state = LV_INDEV_STATE_PRESSED;
        }
        else if (key == 39) //right
        {
            keypad.key = LV_KEY_RIGHT;
            keypad.state = LV_INDEV_STATE_PRESSED;
        }
        else if (key == 40) //down
        {
            keypad.key = LV_KEY_DOWN;
            keypad.state = LV_INDEV_STATE_PRESSED;
        }
        else if (key == 46) //delete
        {
            keypad.key = LV_KEY_DEL;
            keypad.state = LV_INDEV_STATE_PRESSED;
        }
        else if (key == 78) //'n' -> next
        {
            button.btn_id = LV_USER_BTN_NEXT;
            button.state = LV_INDEV_STATE_PRESSED;
        }
        else if (key == 80) //'p' -> prev
        {
            button.btn_id = LV_USER_BTN_PREV;
            button.state = LV_INDEV_STATE_PRESSED;
        }
        else if (key == 83) //'s' -> source
        {
            button.btn_id = LV_USER_BTN_SOURCE;
            button.state = LV_INDEV_STATE_PRESSED;
        }
        else if (key == 98) //'2'
        {
            encoder.val++;
        }
        else if (key == 101) //'5'
        {
            encoder.state = LV_INDEV_STATE_PRESSED;
        }
        else if (key == 104) //'8'
        {
            encoder.val--;
        }
    }
    else if (event == KEYBD_EVENT_UP)
    {
        if (key == 8) //backspace
        {
            keypad.key = LV_KEY_BACKSPACE;
            keypad.state = LV_INDEV_STATE_RELEASED;
        }
        else if (key == 13) //enter
        {
            keypad.key = LV_KEY_ENTER;
            keypad.state = LV_INDEV_STATE_RELEASED;
        }
        else if (key == 27) //esc
        {
            keypad.key = LV_KEY_ESC;
            keypad.state = LV_INDEV_STATE_RELEASED;
        }
        else if (key == 32) //' ' -> play & pause
        {
            button.btn_id = LV_USER_BTN_PLAY_PAUSE;
            button.state = LV_INDEV_STATE_RELEASED;
        }
        else if (key == 33) //page up
        {
            keypad.key = LV_KEY_PREV;
            keypad.state = LV_INDEV_STATE_RELEASED;
        }
        else if (key == 34) //page dwon
        {
            keypad.key = LV_KEY_NEXT;
            keypad.state = LV_INDEV_STATE_RELEASED;
        }
        else if (key == 35) //end
        {
            keypad.key = LV_KEY_END;
            keypad.state = LV_INDEV_STATE_RELEASED;
        }
        else if (key == 36) //home
        {
            keypad.key = LV_KEY_HOME;
            keypad.state = LV_INDEV_STATE_RELEASED;
        }
        else if (key == 37) //left
        {
            keypad.key = LV_KEY_LEFT;
            keypad.state = LV_INDEV_STATE_RELEASED;
        }
        else if (key == 38) //up
        {
            keypad.key = LV_KEY_UP;
            keypad.state = LV_INDEV_STATE_RELEASED;
        }
        else if (key == 39) //right
        {
            keypad.key = LV_KEY_RIGHT;
            keypad.state = LV_INDEV_STATE_RELEASED;
        }
        else if (key == 40) //down
        {
            keypad.key = LV_KEY_DOWN;
            keypad.state = LV_INDEV_STATE_RELEASED;
        }
        else if (key == 46) //delete
        {
            keypad.key = LV_KEY_DEL;
            keypad.state = LV_INDEV_STATE_RELEASED;
        }
        else if (key == 78) //'n' -> next
        {
            button.btn_id = LV_USER_BTN_NEXT;
            button.state = LV_INDEV_STATE_RELEASED;
        }
        else if (key == 80) //'p' -> prev
        {
            button.btn_id = LV_USER_BTN_PREV;
            button.state = LV_INDEV_STATE_RELEASED;
        }
        else if (key == 83) //'s' -> source
        {
            button.btn_id = LV_USER_BTN_SOURCE;
            button.state = LV_INDEV_STATE_RELEASED;
        }
        else if (key == 101) //'5'
        {
            encoder.state = LV_INDEV_STATE_RELEASED;
        }
    }
}

static void lv_pointer_driver_read_callback(lv_indev_drv_t *drv, lv_indev_data_t *data)
{
    data->state = pointer.state;
    data->point.x = pointer.x;
    data->point.y = pointer.y;
}

static void lv_keypad_driver_read_callback(lv_indev_drv_t *drv, lv_indev_data_t *data)
{
    data->state = keypad.state;
    data->key = keypad.key;
}

static void lv_encoder_driver_read_callback(lv_indev_drv_t *drv, lv_indev_data_t *data)
{
    data->state = encoder.state;
    data->enc_diff = encoder.val;
    encoder.val = 0;
}

static void lv_button_driver_read_callback(lv_indev_drv_t *drv, lv_indev_data_t *data)
{
    data->state = button.state;
    data->btn_id = button.btn_id;
}

void lv_port_indev_init(void)
{
    static lv_indev_drv_t pointer_driver;
    static lv_indev_drv_t keypad_driver;
    static lv_indev_drv_t encoder_driver;
    static lv_indev_drv_t button_driver;
    lv_group_t* group;
    
	VirtLCD_SetMouseProc(mouse_callback);
	VirtLCD_SetKeybdProc(keyboard_callback);
	
    lv_indev_drv_init(&pointer_driver);
    pointer_driver.type = LV_INDEV_TYPE_POINTER;
    pointer_driver.read_cb = lv_pointer_driver_read_callback;
    lv_pointer_device_object = lv_indev_drv_register(&pointer_driver);

    lv_indev_drv_init(&keypad_driver);
    keypad_driver.type = LV_INDEV_TYPE_KEYPAD;
    keypad_driver.read_cb = lv_keypad_driver_read_callback;
    lv_keypad_device_object = lv_indev_drv_register(&keypad_driver);

    lv_indev_drv_init(&encoder_driver);
    encoder_driver.type = LV_INDEV_TYPE_ENCODER;
    encoder_driver.read_cb = lv_encoder_driver_read_callback;
    lv_encoder_device_object = lv_indev_drv_register(&encoder_driver);

    lv_indev_drv_init(&button_driver);
    button_driver.type = LV_INDEV_TYPE_BUTTON;
    button_driver.read_cb = lv_button_driver_read_callback;
    lv_button_device_object = lv_indev_drv_register(&button_driver);

    group = lv_group_get_default();
    if (!group)
    {
        LV_LOG_WARN(
            "The default group object is NULL. Create a new group object "
            "and set it to default instead.");

        group = lv_group_create();
        if (group)
        {
            lv_group_set_default(group);
        }
    }
    lv_indev_set_group(lv_keypad_device_object, group);
    lv_indev_set_group(lv_encoder_device_object, group);
    lv_indev_set_button_points(lv_button_device_object, button_points);
}

int lv_indev_get_user_button(lv_point_t *point)
{
    int btn = LV_USER_BTN_UNDEFINED;
    int i;
    
    for (i=0; i<LV_USER_BTN_MAX; i++)
    {
        if (point->x==button_points[i].x && point->y==button_points[i].y)
        {
            btn = i;
            break;
        }
    }
    return btn;
}


